#include <iostream>
#include <string>
#include "user.pb.h"
#include "mprpcapplication.h"
#include "rpcprovider.h"

/*
UserService原来是一个本地服务，提供了两个进程内的本地方法，Login和GetFriendLists
*/
class UserService : public fixbug::UserServiceRpc // 这个UserService是使用在rpc服务的发布端（rpc服务提供者）
{
public:
  bool Login(std::string name, std::string pwd)
  {
    std::cout << "doing local service: Login" << std::endl;
    std::cout << "name:" << name << " pwd:" << pwd << std::endl;
    return false;
  }

  bool Register(uint32_t id, std::string name, std::string pwd)
  {
    std::cout << "doing local service: Register" << std::endl;
    std::cout << "id:" << id << "name:" << name << " pwd:" << pwd << std::endl;
    return true;
  }

  /*
    重写基类UserServiceRpc的虚函数 下面这些方法都是框架直接调用的
    1. caller RPC调用者   ===>   Login(LoginRequest)打包  => muduo库 =>   callee端
    2. callee RPC提供者   ===>   根据接收到的Login(LoginRequest)  => 交到下面重写的这个Login方法上了
    */
  void Login(::google::protobuf::RpcController *controller,
             const ::fixbug::LoginRequest *request,
             ::fixbug::LoginResponse *response,
             ::google::protobuf::Closure *done)
  {
    // 框架给业务上报了请求参数LoginRequest，应用程序获取相应数据做本地业务（登录的本地业务）
    std::string name = request->name();
    std::string pwd = request->pwd();
    /*这个就是使用protobuf的好处，protobuf直接把字节流反序列化成我们可以识别的LoginRequest对象，通过
    他生成的方法获取姓名和密码。
    */

    // 做本地业务
    bool login_result = Login(name, pwd); // 等于当前的本地方法

    // 框架只是创建一个LoginResponse，我们只需要把响应写入，包括错误码、错误消息、返回值
    fixbug::ResultCode *code = response->mutable_result();
    code->set_errcode(0);
    code->set_errmsg(""); // 没有错误
    response->set_sucess(login_result);

    // 执行回调操作，执行响应对象数据的序列化和网络发送（都是由框架来完成的）
    // Closure是一个抽象类，重写Run,让它去做一些事情
    done->Run();
  }

  //注册的方法
    void Register(::google::protobuf::RpcController* controller,
                       const ::fixbug::RegisterRequest* request,
                       ::fixbug::RegisterResponse* response,
                       ::google::protobuf::Closure* done)
    {
        uint32_t id = request->id();
        std::string name = request->name();
        std::string pwd = request->pwd();

        bool ret = Register(id, name, pwd);

        response->mutable_result()->set_errcode(0);
        response->mutable_result()->set_errmsg("");
        response->set_sucess(ret);

        done->Run();
    }

};




int main(int argc, char **argv) // 需要配置文件
{
  // 调用框架的初始化操作
  MprpcApplication::Init(argc, argv); // 整个框架的初始化操作，日志，配置等等。

  // provider是一个rpc网络的服务对象。把UserService对象发布到rpc节点上。
  RpcProvider provider;
  provider.NotifyService(new UserService()); // 发布服务
  // 可以调用多次，生成多个远程RPC服务

  // 启动一个rpc服务发布节点
  provider.Run();
  // Run以后，进程进入阻塞状态，等待远程的rpc调用请求

  return 0;
}
